<template>
  <div class="upload-container upload-custom-container">
    <div>
      <draggable v-if="isImg" v-model="newValue" @end="dragEnd">
        <div v-for="(item, i) in newValue" :key="i" class="card animated fadeInDown">
          <div v-if="item.url" class="img-wrapper">
            <img :src="item.url">
          </div>
          <div class="ctrl-wrapper">
            <a-icon @click="previewImage(item, i)" type="eye"/>
            <a-icon @click="remove(item, i)" type="delete"/>
          </div>
        </div>
      </draggable>
      <div
        @click="showUpload"
        v-if="newValue && newValue.length < limit"
        class="card"
        :class="isImg ? 'add-card' : 'add-not-card'"
      >
        <a-icon type="plus"/>
        <input
          :multiple="limit > 1"
          @change="upload"
          :accept="accept"
          type="file"
          v-show="false"
          ref="input"
        >
      </div>
      <draggable v-if="!isImg" v-model="newValue" @end="dragEnd">
        <div v-for="(item, i) in newValue" :key="i" class="uploaded-item middle-flex">
          <div @click="priview(item.url)" class="video-src">{{item.url}}</div>
          <a-icon type="delete" @click="remove(item, i)"/>
        </div>
      </draggable>
    </div>
    <p v-if="tip" class="tip">{{tip}}</p>
    <div v-if="openPercentage" class="percentage">
      <a-progress type="circle" :percent="percentage"></a-progress>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import draggable from 'vuedraggable'
import { loading } from 'kuan-request'
import uploader from 'kuan-utils/lib/uploader'

import { qnToken } from '@/api/uploadToken'

export default {
  props: {
    value: {
      type: Array
    },
    tip: {
      type: String,
      default: ''
    },
    limit: {
      type: Number,
      default: 1
    },
    size: {
      type: Number,
      default: 60000
    },
    accept: {
      type: String,
      default: 'image/*'
    },
    action: {
      type: String,
      default: 'https://upload.qiniup.com'
    },
    module: {
      type: String,
      default: ''
    },
    private: {
      type: Boolean,
      default: false
    },
    validate: {
      type: Function
    }
  },
  computed: {
    isImg() {
      return this.accept === 'image/*';
    }
  },
  watch: {
    value: {
      handler() {
        this.newValue = this.value
      },
      deep: true
    }
  },
  data() {
    return {
      newValue: this.value || [],
      formData: {
        token: '',
        'x:module': this.module
      },
      percentage: 0, // 上传视频进度条
      openPercentage: false
    };
  },
  methods: {
    async getName(file) {
      const { name } = file
      const md5Name = await uploader.getFileMD5(file)
      const suffix = name.substr(name.lastIndexOf('.'))
      return md5Name + suffix
    },
    async beforeUpload(file) {
      if (file.size / 1000 > this.size) {
        const message = '图片过大';
        this.$message.warning(message);
        return Promise.reject(message);
      }
      if (this.validate) {
        await this.validate(file);
      }
      this.formData.token = await qnToken(this.private);
      this.formData.resource_key = await this.getName(file)
      return true;
    },
    async showUpload() {
      const { input } = this.$refs;
      input.click();
    },
    async uploadItem(file) {
      await this.beforeUpload(file);
      if (this.size > 100000) {
        this.openPercentage = true
      } else {
        loading.show()
      }
      const fd = new FormData();
      fd.append('file', file);

      Object.entries(this.formData).forEach(([key, value]) => {
        fd.append(key, value);
      });
      const { data } = await axios({
        url: this.action,
        method: 'post',
        data: fd,
        onUploadProgress: ({ loaded, total }) => {
          this.percentage = Math.floor(loaded / total * 100) || 0.5
        }
      });
      const { base_url, id, path, width, height } = data;
      const item = {
        url: this.isImg ? `${base_url}${path}!300x300` : `${base_url}${path}`,
        id: id,
        path: path,
        width,
        height
      };
      this.newValue.push(item);
      this.$emit('success', item);
      this.change();
      if (this.size > 100000) {
        this.openPercentage = false
      } else {
        loading.hide()
      }
    },
    upload() {
      const { files = [] } = this.$refs.input;
      try {
        for (let i = 0; i < files.length; i++) {
          this.uploadItem(files[i]);
        }
      } catch (e) {
        this.$message.warning(e.message);
      }
    },
    change() {
      const value = this.newValue;
      this.$emit('input', value);
      this.$emit('change', value);
    },
    remove(item, i) {
      this.newValue = this.newValue.filter((it, index) => index !== i);
      this.change();
      this.$emit('remove', item);
    },
    dragEnd() {
      this.change();
      this.$emit('sort', this.newValue);
    },
    previewImage(item) {
      this.$preview(item.url)
    },
    priview(url) {
      if (!url) return
      window.open(url)
    }
  },
  components: {
    draggable
  }
};
</script>

<style lang="scss" scoped>
.percentage {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100001;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  justify-content: center;
  align-items: center;
}
.upload-container {
  display: inline-block;
}

.card {
  overflow: hidden;
  border-radius: 6px;
  box-sizing: border-box;
  width: 120px;
  height: 120px;
  margin: 0 8px 8px 0;
  display: inline-block;
  border: 1px solid #c0ccda;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  &:hover {
    .ctrl-wrapper {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }
  &.add-card {
    border: 1px dashed #c0ccda;
    background-color: #fbfdff;
    font-size: 28px;
    color: #8c939d;
    &:hover {
      border-color: #409eff;
      color: #409eff;
    }
  }
  &.add-not-card {
    border: 1px dashed #c0ccda;
    background-color: #fbfdff;
    font-size: 20px;
    color: #8c939d;
    width: 50px;
    height: 50px;
    .el-icon-plus {
      display: flex;
      justify-content: center;
      margin-top: 14px;
    }
  }
  .img-wrapper {
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    img {
      width: 100%;
    }
  }
}

.ctrl-wrapper {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  color: white;
  font-size: 20px;
  display: none;
  i {
    padding: 0 8px;
  }
}
.uploaded-item {
  line-height: 1;
  cursor: pointer;
  i {
    padding: 0 10px;
  }
}
.tip {
  color: gray;
  padding: 0;
  margin: 0;
}
.video-src {
  display: inline-block;
  width: 350px;
  overflow: hidden;
  white-space: nowrap;
}
</style>

<style>
.upload-custom-container > div {
  display: inline-block;
}
</style>
